package com.ruoyi.security.service.backtest.gridtrading.processor;

import com.ruoyi.security.enums.BenchmarkPriceUpdateTypeEnum;
import com.ruoyi.security.service.backtest.gridtrading.charge.SecurityTradeChargeService;
import com.ruoyi.security.service.backtest.gridtrading.context.BacktestContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Optional;

/**
 * @author yeoman
 * @date 2025/11/7 23:28
 * @description 抽象交易处理器
 */
@Slf4j
@Component
public abstract class AbstractTradeProcessor implements ITradeProcessorService {

    @Resource
    private SecurityTradeChargeService securityTradeChargeService;

    /**
     * 更新交易上下文
     * @param context 交易上下文
     */
    protected abstract void updateContext(BacktestContext context);

     @Override
    public void process(BacktestContext context) {
         BacktestContext.BacktestParam backtestParam = context.getBacktestParam();
         BacktestContext.BacktestParam.TradeCharge tradeCharge = backtestParam.getTradeCharge();
         BacktestContext.BacktestParam.InitialValue initialValue = backtestParam.getInitialValue();
         BacktestContext.BacktestParam.TriggerMandateSettings triggerMandateSettings = backtestParam.getTriggerMandateSettings();
         BacktestContext.BacktestVariable backtestVariable = context.getBacktestVariable();
         BacktestContext.BacktestVariable.TradeInfo tradeInfo = backtestVariable.getTradeInfo();
         BacktestContext.BacktestVariable.TotalTradeInfo totalTradeInfo = backtestVariable.getTotalTradeInfo();
         BacktestContext.BacktestVariable.DayTradeInfo dayTradeInfo = backtestVariable.getDayTradeInfo();

         BigDecimal tradePrice = tradeInfo.getTradePrice();
         // 计算交易金额 = 交易价格 * 交易数量
         BigDecimal tradeAmount = tradePrice.multiply(new BigDecimal(tradeInfo.getTradeQuantity()));
         // 更新当前交易金额
         tradeInfo.setTradeAmount(tradeAmount);
         // 计算交易手续费
         BigDecimal tradeChargeAmount = securityTradeChargeService.calculateCharge(tradeInfo.getTradeType(), tradeAmount,
                 tradeCharge.getCommissionTenThousandth(), tradeCharge.getMinimumCommission());
         // 更新当前交易手续费
         context.getBacktestVariable().getTradeInfo().setTradeChargeAmount(tradeChargeAmount);
         // 更新上下文
         updateContext(context);
         // 计算触发价
         BigDecimal triggerPrice = triggerMandateSettings.getRiseFallTypeCalcStrategy()
                 .calculateTriggerPrice(backtestVariable.getBenchmarkPrice(), tradeInfo.getTradeMultiple(),
                         backtestVariable.getPerRiseFallValue(), tradeInfo.getTradeType());
         // 更新触发价
         backtestVariable.setTriggerPrice(triggerPrice);
         // 按触发价格更新基准价
         if (BenchmarkPriceUpdateTypeEnum.BY_TRIGGER_PRICE.getKey().equals(triggerMandateSettings.getBenchmarkPriceUpdateType())) {
             backtestVariable.setBenchmarkPrice(backtestVariable.getTriggerPrice());
         }
         // 按成交价格更新基准价
         else if (BenchmarkPriceUpdateTypeEnum.BY_DEAL_PRICE.getKey().equals(triggerMandateSettings.getBenchmarkPriceUpdateType())) {
             backtestVariable.setBenchmarkPrice(tradePrice);
         }
         // 更新成本价 = (初始市值 + 总的买入金额 - 总的卖出金额) / 当前持仓数量
         totalTradeInfo.setCostPrice(initialValue.getInitialMarketValue()
                 .add(totalTradeInfo.getBuy().getTotalBuyAmount())
                 .subtract(totalTradeInfo.getSell().getTotalSellAmount())
                 .divide(new BigDecimal(backtestVariable.getPosition()), 2, RoundingMode.HALF_UP));
         // 更新收益相关指标
         context.updateProfit(tradePrice);

         // 更新当日交易次数
         dayTradeInfo.getTrade().setDayTradeCount(dayTradeInfo.getTrade().getDayTradeCount() + 1);
         // 更新当日交易数量
         dayTradeInfo.getTrade().setDayTradeQuantity(dayTradeInfo.getTrade().getDayTradeQuantity() + tradeInfo.getTradeQuantity());
         // 更新当日交易金额
         dayTradeInfo.getTrade().setDayTradeAmount(dayTradeInfo.getTrade().getDayTradeAmount().add(tradeAmount));
         // 更新当日交易手续费
         dayTradeInfo.getTrade().setDayTradeChargeAmount(dayTradeInfo.getTrade().getDayTradeChargeAmount().add(tradeChargeAmount));

         // 更新总的交易次数
         totalTradeInfo.getTrade().setTotalTradeCount(totalTradeInfo.getTrade().getTotalTradeCount() + 1);
         // 更新总的交易数量
         totalTradeInfo.getTrade().setTotalTradeQuantity(totalTradeInfo.getTrade().getTotalTradeQuantity() + tradeInfo.getTradeQuantity());
         // 更新总的交易金额
         totalTradeInfo.getTrade().setTotalTradeAmount(totalTradeInfo.getTrade().getTotalTradeAmount().add(tradeAmount));
         // 更新总的交易手续费
         totalTradeInfo.getTrade().setTotalTradeChargeAmount(totalTradeInfo.getTrade().getTotalTradeChargeAmount().add(tradeChargeAmount));
         // 更新市值
         backtestVariable.setMarketValue(tradePrice.multiply(new BigDecimal(backtestVariable.getPosition())));
         // 更新总资产
         backtestVariable.setTotalAssets(backtestVariable.getMarketValue().add(Optional.ofNullable(backtestVariable.getAvailableAmount()).orElse(BigDecimal.ZERO)));
     }

}
